﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OverStore.Runtime.PersistenceServiceProvider;
using System.Diagnostics;

namespace OverStore.Runtime.ObjectRepository.Attacher
{
    /// <summary>
    /// Implementation of <see cref="IAttacher{TInstance, TIdentifier}"/> interface that uses user-defined delegate for provide attaching info.
    /// </summary>
    /// <typeparam name="TInstance">The type of the instance.</typeparam>
    /// <typeparam name="TIdentifier">The type of the identifier.</typeparam>
    public class DelegateAttacher<TInstance, TIdentifier> : IAttacher<TInstance, TIdentifier>
        where TInstance : class
    {
        private readonly Action<TInstance, IPersistenceServiceProvider, InstanceAttachInfo<TIdentifier>> _ProvideAttachInfo;
        private readonly IPersistenceServiceProvider _Provider;

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegateAttacher&lt;TInstance, TIdentifier&gt;"/> class.
        /// </summary>
        /// <param name="provider">The provider.</param>
        /// <param name="provideAttachInfo">The provide attach info.</param>
        public DelegateAttacher(IPersistenceServiceProvider provider, Action<TInstance, IPersistenceServiceProvider, InstanceAttachInfo<TIdentifier>> provideAttachInfo)
        {
            if (Object.ReferenceEquals(provideAttachInfo, null))
                throw new ArgumentNullException("provideAttachInfo");
            if (Object.ReferenceEquals(provider, null))
                throw new ArgumentNullException("provider");
            _Provider = provider;
            _ProvideAttachInfo = provideAttachInfo;
        }

        /// <summary>
        /// Provides the info for attaching instance.
        /// </summary>
        public void ProvideAttachInfo(TInstance instance, InstanceAttachInfo<TIdentifier> attachInfo)
        {
            Debug.Assert(instance != null, "instance != null");
            Debug.Assert(attachInfo != null, "attachInfo != null");

            try
            {
                _ProvideAttachInfo(instance, _Provider, attachInfo);
            }
            catch (Exception ex)
            {
                throw new PersistingRuntimeException(
                    String.Format("The error is occured due requesting attach info for the instance of type {0}.", typeof(TInstance)),
                    ex);
            }
        }
    }
}
